#define _GNU_SOURCE
#include "app_serial.h"
#include <log.h>

// 0  还原初始设置
int app_serial_makeraw(Device *device)
{ // 0 准备
    int fd = device->fd;
    struct termios termios_attr;
    // 1  取出当前配置
    if (tcgetattr(fd, &termios_attr) < 0)
    {
        perror("tcgetattr failed");
        return -1;
    }
    // 2  还原初始设置
    cfmakeraw(&termios_attr);
    // 3 写入配置
    tcsetattr(fd, TCSAFLUSH, &termios_attr);

    return 0;
}

// 1   波特率
int app_serial_set_baudrate(Device *device, SerialBaudRate baudrate)
{
    // 0 准备
    int fd = device->fd;
    struct termios termios_attr;
    // 1  取出当前配置
    if (tcgetattr(fd, &termios_attr) < 0)
    {
        perror("tcgetattr failed");
        return -1;
    }
    // 2  修改配置
    cfsetspeed(&termios_attr, baudrate);
    // 3 写入配置
    tcsetattr(fd, TCSAFLUSH, &termios_attr);
    return 0;
}
// 2   停止位
int app_serial_set_stopbits(Device *device, SerialStopBits stopbits)
{
    // 0 准备
    int fd = device->fd;
    struct termios termios_attr;
    // 1  取出当前配置
    if (tcgetattr(fd, &termios_attr) < 0)
    {
        perror("tcgetattr failed");
        return -1;
    }
    // 2  修改配置
    termios_attr.c_cflag &= ~CSTOPB;  // 清除停止位
    termios_attr.c_cflag |= stopbits; // 设置停止位

    // 3 写入配置
    tcsetattr(fd, TCSAFLUSH, &termios_attr);

    return 0;
}
// 3   奇偶校验位
int app_serial_set_parity(Device *device, SerialParity parity)
{
    // 0 准备
    int fd = device->fd;
    struct termios termios_attr;
    // 1  取出当前配置
    if (tcgetattr(fd, &termios_attr) < 0)
    {
        perror("tcgetattr failed");
        return -1;
    }
    // 2  修改配置
    termios_attr.c_cflag &= ~(PARENB | PARODD); // 清除校验位、
    termios_attr.c_cflag |= parity;             // 设置校验位

    // 3 写入配置
    tcsetattr(fd, TCSAFLUSH, &termios_attr);

    return 0;
}

// 4   是否阻塞读取
int app_serial_set_blocking(Device *device, int blocking)
{
    // 0 准备
    int fd = device->fd;
    struct termios termios_attr;
    // 1  取出当前配置
    if (tcgetattr(fd, &termios_attr) < 0)
    {
        perror("tcgetattr failed");
        return -1;
    }
    // 2  修改配置  如果 blocking 为 0  则设置为非阻塞 （等200毫秒就走） 1 死等
    if (blocking == 0) // 非阻塞  配置调试解决
    {
        termios_attr.c_cc[VTIME] = 2; // 等多长时间 每个数表示100毫秒
        termios_attr.c_cc[VMIN] = 0;  // 最少读多少个字符
    }
    else if (blocking == 1) // 阻塞状态 日常读取数据的方式
    {
        termios_attr.c_cc[VTIME] = 0; // 无限等待
        termios_attr.c_cc[VMIN] = 1;  // 至少有一条数据
    }

    // 3 写入配置
    tcsetattr(fd, TCSAFLUSH, &termios_attr);

    return 0;
}

/**
 * 初始化设备的串口配置
 */
int app_serial_init(Device *device)
{
    //0 给设备定性：串口
    device->dev_type = DEVICE_TYPE_SERIAL;
    //1 还原设置
    app_serial_makeraw(device);
    //2 设置波特率
    app_serial_set_baudrate(device,BR_115200);
    //3 设置停止位
    app_serial_set_stopbits(device,StopBit_One);
    //4 设置奇偶校验
    app_serial_set_parity(device,Parity_None);

    int ret= tcflush(device->fd,TCIOFLUSH);
    if(ret==0)
    {
        log_info("串口设置成功");
    }else{
        log_error("串口设置失败");
        return -1;
    }
    return 0;

}